package top.rish.universe.core.plugin;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ReUtil;
import org.noear.luffy.model.AFileModel;
import org.noear.solon.Solon;
import org.noear.solon.core.util.IoUtil;
import org.noear.solon.core.util.LogUtil;
import org.noear.solon.luffy.impl.JtExecutorAdapter;
import org.noear.solon.luffy.impl.JtFunctionLoader;
import org.noear.solon.luffy.impl.JtMapping;
import org.noear.solon.luffy.impl.JtRun;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

public class FuckFunctionLoaderFile  implements JtFunctionLoader {

    static Logger log = LoggerFactory.getLogger(FuckFunctionLoaderFile.class);
    private final Map<String, AFileModel> fileCached = new LinkedHashMap<>();

    public File _baseDir;

    public FuckFunctionLoaderFile() {
        this("./");
    }

    protected FuckFunctionLoaderFile(String baseDir) {
        _baseDir = new File(baseDir);
        if (!_baseDir.exists()) {
            _baseDir.mkdirs();
        }
    }


    protected String tryFtl(String path){
        if(ObjUtil.isEmpty(FileNameUtil.getSuffix(path))){
            String tryFtlName = path.concat(".ftl");
            File tryFtl = new File(_baseDir,tryFtlName);
            if(FileUtil.exist(tryFtl)
                    && FileUtil.isFile(tryFtl)){
                return tryFtlName;
            }
            String tryIndexFtlName = path.concat("/index.ftl");
            File tryIndexFtl = new File(_baseDir,tryIndexFtlName);
            if(FileUtil.exist(tryIndexFtl)
                    && FileUtil.isFile(tryIndexFtl)){
                return tryIndexFtlName;
            }
        }
        return path;
    }

    @Override
    public AFileModel fileGet(String path) throws Exception {
        path = "/".concat(path).trim();

        if(path.endsWith("/")){
            path = path.replaceAll("/$","");
        }

        path = path.replaceAll("/+","/");

        path = this.tryFtl(path);

        if(ObjUtil.isEmpty(FileNameUtil.getSuffix(path))) {
            path = path.concat(".ftl");
        }

        File file = fileBuildDo(path);

        if (file == null) {
            //code/sx中国x-23/
            String modPath = ReUtil.get(".*?/",path,0);
            if(null==modPath){
                return null;
            }
            log.error("404error,path:{}"+path);
            file = fileBuildDo(modPath.concat("404.ftl"));
            if(null==file){
                return null;
            }
        }

        AFileModel fileModel = fileCached.get(path);

        if (fileModel == null) {
            synchronized (fileCached) {
                fileModel = fileCached.get(path);

                if (fileModel == null) {
                    fileModel = new AFileModel();
                    fileFillDo(fileModel, file, path);

                    fileCached.put(path, fileModel);
                }
            }
        }

        if (fileModel.update_fulltime == null ||
                fileModel.update_fulltime.getTime() != file.lastModified()) {
            synchronized (fileCached) {
                if (fileModel.update_fulltime == null ||
                        fileModel.update_fulltime.getTime() != file.lastModified()) {
                    fileFillDo(fileModel, file, path);
                }

                if(fileModel.content != null){
                    //如果有更新，移除缓存
                    JtRun.dele(path);
                }
            }
        }

        return fileModel;
    }

    protected void fileFillDo(AFileModel fileModel, File file, String path) throws Exception {
        String suffix =  FileNameUtil.getSuffix(path);
        String edit_mode = JtMapping.getActuator(suffix);
        if(ObjUtil.isEmpty(edit_mode)){
            return;
        }
        fileModel.content = fileContentGet(file);

        if (fileModel.content != null) {
            //如果有找到文件内容，则完善信息
            //
            String fileName = file.getName();

            if (fileModel.file_id == 0) {
                //如果还没有 id 说明是第一次加载
                fileModel.path = path;
                fileModel.tag = "code";
                fileModel.edit_mode = edit_mode;

                //有些场景需要id
                fileModel.file_id = Math.abs(path.hashCode());
            }

            fileModel.update_fulltime = new Date(file.lastModified());
        }
    }

    protected File fileBuildDo(String path) {
        if (_baseDir == null) {
            return null;
        } else {
            File file = new File(_baseDir, path);

            if (file.exists()) {
                return file;
            } else {
                return null;
            }
        }
    }

    protected String fileContentGet(File file) {
        try {
            try (InputStream ins = new FileInputStream(file)) {
                String s = IoUtil.transferToString(ins, Solon.encoding());
                if(ObjUtil.isNotEmpty(s)){
                    s = s.replaceAll("\\uFEFF","");
                }
                return s;
            }
        } catch (IOException e) {
            log.warn(e.getMessage(), e);
            return null;
        }
    }
}